﻿/*
   Open Intel 
   Copyright © 2011 – ISC. All Rights Reserved.
*/

using System;
using System.Collections.Generic;
using Caliburn.Micro;
using ISC.MapDotNetServer.Common;
using ISC.MapDotNetServer.Common.Data;
using ISC.RIM.Silverlight.MDNSFeatureService;
using OI.Framework;

namespace OI.Async
{
    public abstract class MDNFeatureQueryBase : IResult
    {
        FeatureServiceClient _Client;
        public event EventHandler<ResultCompletionEventArgs> Completed;

        // results
        public List<QueryResultTable> Results { get; private set; }

        // override these for concrete queries
        protected abstract QueryRequest BuildQueryRequest();
        protected abstract IEnumerable<Query> BuildQueries();


        // mdn feature service proxy
        protected FeatureServiceClient Client
        {
            get
            {
                return _Client ?? (_Client = ServiceClients.CreateFeatureServiceClient(QueryCompleted));
            }
        }


        // execute the query here
        public virtual void Execute(ActionExecutionContext context)
        {
            var request = BuildQueryRequest();

            var requestId = Guid.NewGuid();

            BuildQueries().Apply(x => request.Queries.Add(x));

            Client.QueryAsync(request.Serialize(), requestId);
        }


        // connection specification using an actual database connection string
        protected AbstractDataSourceSpecification CreateDataSourceSpecication(string table, ProjCoordSys projection, GeometryTypes type, string whereClause)
        {
            return new ConnectionDataSourceSpecification
            {
                Connection = Configuration.ConnectionString,
                ConnectionType = ConnectionDataSourceSpecification.ConnectionTypes.SqlServer2008,
                Projection = projection,
                GeometryColumn = "GeometryItem",
                Type = type,
                DataTable = table,
                WhereClause = whereClause
            };
        }


        // connection specification using a map and layer id
        protected AbstractDataSourceSpecification CreateDataSourceSpecication(string mapID, string layerID, string whereClause)
        {
            return new MapLayerDataSourceSpecification
            {
               MapID = mapID,
               LayerID = layerID,
               WhereClauseOverride = whereClause,
            };
        }


        // handle the results
        void QueryCompleted(object sender, QueryCompletedEventArgs e)
        {
            try
            {
                if (e.Error != null)
                {
                    HandleError(e.Error);
                    return;
                }

                var response = QueryResponse.Deserialize(e.Result);

                // check error at query-group level
                if (!string.IsNullOrEmpty(response.Error))
                {
                    HandleError(new Exception(response.Error));
                    return;
                }

                // check for individual query errors
                response.QueryResultTables.ForEach((x) =>
                {
                    if (x.Error != null)
                    {
                        HandleError(new Exception(x.Error));
                    }
                });

                Results = response.QueryResultTables;
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
            finally
            {
                Completed(this, new ResultCompletionEventArgs());
            }
        }


        // forward error to IShell
        static void HandleError(Exception ex)
        {
            if (ex != null)
            {
                IoC.Get<IShell>().HandleException(ex, "Query error:");
            }
        }
    }
}
